﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Qreed.Drawing.Drawing2D;
using System.Diagnostics;
using System.Drawing.Drawing2D;

namespace Qreed.Drawing.TriDemo
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            // float f = Polygon2D.GetVectorLength(new PointF(1.0f, 1.0f), new PointF());

        }

        private List<PointF> _vertices = new List<PointF>();
        private List<List<PointF>> _verticesInner = new List<List<PointF>>();
        private Polygon2DOld _polygon;

        private void _pnlCanvas_MouseClick(object sender, MouseEventArgs e)
        {
            PointF pt = new PointF(e.X, e.Y);

            if (e.Button == MouseButtons.Left)
            {
                AddVertex(pt, _vertices, null);
            }
            else if(e.Button == MouseButtons.Right)
            {
                if (_polygon == null)
                {
                    MessageBox.Show("Create other polygon first (left click).", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                else
                {
                    while (_verticesInner.Count == 0)
                        _verticesInner.Add(new List<PointF>());

                    AddVertex(pt, _verticesInner[0], _polygon);
                }
            }
            else if (e.Button == MouseButtons.Middle)
            {
                if (_polygon == null)
                {
                    MessageBox.Show("Create other polygon first (left click).", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                else
                {
                    while (_verticesInner.Count <= 1)
                        _verticesInner.Add(new List<PointF>());

                    AddVertex(pt, _verticesInner[1], _polygon);
                }
            }

            UpdatePolygons();

            _pnlCanvas.Invalidate();
        }

        private void UpdatePolygons()
        {
            _polygon = ConstructPolygon(_vertices);

            if (_polygon != null)
            {
                List<Polygon2DOld> holes = new List<Polygon2DOld>();

                foreach (List<PointF> vertices in _verticesInner)
                {
                    Polygon2DOld polygon = ConstructPolygon(vertices);

                    if(polygon != null)
                        holes.Add(polygon);
                }

                _polygon.Subtract(holes.ToArray());
            }            
        }

        private Polygon2DOld ConstructPolygon(List<PointF> vertices)
        {
            Polygon2DOld ret = null;

            if (vertices.Count >= 3)
            {
                try
                {
                    ret = new Polygon2DOld(vertices);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message, "Exception", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    vertices.RemoveAt(vertices.Count - 1);

                    if (vertices.Count >= 3)
                        ret = new Polygon2DOld(vertices);
                }
            }

            return ret;
        }

        private static void AddVertex(PointF pt, List<PointF> vertices, Polygon2DOld checkIfInside)
        {
            if (checkIfInside != null &&
                !checkIfInside.Contains(pt))
            {
                MessageBox.Show("Point not within polygon.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            vertices.Add(pt);
        }
        
        private void pnlCanvas_Paint(object sender, PaintEventArgs e)
        {
            /*foreach (Triangle t in _triangles)
            {
                e.Graphics.DrawLine(Pens.Black, t.Vertex1, t.Vertex2);
                e.Graphics.DrawLine(Pens.Black, t.Vertex2, t.Vertex3);
                e.Graphics.DrawLine(Pens.Black, t.Vertex3, t.Vertex1);
            }*/

            if (_polygon != null)
            {
                e.Graphics.FillPolygon(Brushes.LightGray, _polygon.Vertices.ToArray());
                e.Graphics.DrawPolygon(Pens.Gray, _polygon.Vertices.ToArray());
                
                /*foreach(LineSegment2D edge in _polygon.Edges)
                {
                    e.Graphics.DrawPolygon(Pens.Black, edge.*/
                
                List<PointF> allReadyDone = new List<PointF>();

                for (int i = 0; i < _polygon.Vertices.Count; i++)
                {
                    PointF v = _polygon.Vertices[i];
                    bool b = false;

                    foreach (PointF pt in allReadyDone)
                    {
                        if (v.X == pt.X && v.Y == pt.Y)
                        {
                            b = true;
                            break;
                        }
                    }

                    float y = v.Y - 15.0f;

                    if (b)
                        y += 20.0f;
                    else
                        allReadyDone.Add(v);

                    e.Graphics.DrawString(i.ToString(), Font, Brushes.Black, new PointF(v.X - 15.0f, y));
                }
            }

            for (int i = 0; i < _vertices.Count; i++)
            {
                PointF v = _vertices[i];
                e.Graphics.FillEllipse(Brushes.Red, new RectangleF(v.X - 4.0f, v.Y - 4.0f, 8.0f, 8.0f));
            }

            foreach (List<PointF> vertices in _verticesInner)
            {
                foreach (PointF v in vertices)
                {
                    e.Graphics.FillEllipse(Brushes.Green, new RectangleF(v.X - 4.0f, v.Y - 4.0f, 8.0f, 8.0f));
                }
            }
        }

        private void _btnClear_Click(object sender, EventArgs e)
        {
            _vertices.Clear(); _verticesInner.Clear();
            _polygon = null;

            _pnlCanvas.Invalidate();
        }

        private void _pnlCanvas_MouseMove(object sender, MouseEventArgs e)
        {
            Text = string.Format("x: {0}, y: {1}", e.X, e.Y);
        }

        private void _btnAddText_Click(object sender, EventArgs e)
        {
            _btnClear_Click(null, null);

            GraphicsPath gp = new GraphicsPath();

            FontFamily ff = new FontFamily("Arial");

            gp.AddString(_txtText.Text, ff, (int)FontStyle.Regular, 1.0f, new Point(0, 0), StringFormat.GenericDefault);
            //gp.Flatten();

            float scale = float.Parse(_txtTextScale.Text);
            
            Matrix m = new Matrix();
            m.Scale(scale, scale);

            float flatness = float.Parse(_txtTextFlatness.Text);

            gp.Flatten(m, flatness);

            Figure2D shape = new Figure2D(gp);


            int i = 0;

            do
            {
                AddVertex(gp.PathPoints[i], _vertices, null);
            } while ((gp.PathTypes[i++] & 0x80) != 0x80);

            while (i < gp.PathTypes.Length)
            {
                _verticesInner.Add(new List<PointF>());

                do
                {
                    AddVertex(gp.PathPoints[i], _verticesInner[_verticesInner.Count-1], null);
                } while ((gp.PathTypes[i++] & 0x80) != 0x80);
            }

           /* if (i < gp.PathTypes.Length)
            {
                do
                {
                    AddVertex(gp.PathPoints[i], _verticesInner, null);
                } while ((gp.PathTypes[i++] & 0x80) != 0x80);
            }*/

            UpdatePolygons();
            _pnlCanvas.Invalidate();
        }

        
    }
}
